<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>函数防抖</title>
</head>

<body>
    
</body>
<script>
//函数防抖，就是指触发事件后，在 n 秒内函数只能执行一次，如果触发事件后在 n 秒内又触发了事件，则会重新计算函数延执行时间。
// 函数防抖
function debounce(fn,delay){
    var timerId ;
    return  function() {
        clearInterval(timerId);
        timerId = setTimeout(fn,delay);
    }  
}
// 1秒之后执行，若在1秒被执行，会取消之前的参数执行
function fun(){
    console.log('窗口发生了改变');
}
var func = debounce(fun,1000);
window.addEventListener("resize",debounce(handle,1000));

// 防抖函数
function debounce2(handle,wait,immediate){
    //首先进行参数判断
    if(typeof handle !== 'function') throw new Error('handle must be function')
    //默认wait为1s
    if(typeof handle === 'undefinde') wait = 1000 
    //如果只传入 handle 和 immediate
    if(typeof wait === 'boolean'){
        immediate = wait
        wait = 1000
    }
    //immediate默认为flase
    if(typeof immediate !== 'boolean') immediate = false
    //所谓的防抖效果，我们想要实现的就是一个人为可以管理handle的执行次数
    let timer = null
    return function proxy(...args){
        let self = this,
        init = immediate && !timer
        clearTimeout(timer)
        timer = setTimeout(()=>{
            timer = null
            !immediate ? handle.aplly(self,args) : null
        },
        wait)
        //如果立即执行
        init ? handle.apply(self,args) : null
    }
}

// 函数节流,就是指触发事件后，在n秒内函数只能执行一次，如果触发事件后在n秒内又触发了事件，则会再次执行该事件。顾名思义，就是像水管流水一样，有频率的执行。
// 函数节流
//通过时间差实现
function throttle1(handle,wait,immediate){
    if (typeof handle !== 'function') throw new Error('handle must be an function')
    if (typeof wait === 'undefined') wait = 1000
    //如果只传入 handle 和 immediate
    if(typeof wait === 'boolean'){
        immediate = wait
        wait = 1000
    }
    //immediate默认为flase
    if(typeof immediate !== 'boolean') immediate = false
    //定义变量记录上一次执行的时间
    let previous = 0
    let timer = null
    return function proxy(...args){
        //获取当前时间
        let now = new Date()
        let self = this
        //如果不立即执行
        if(!immediate) previous = now
        // 计算间隔时间
        let interval = wait - (now - previous)
        if(interval <= 0){
            // 此刻就说明是一个非高频次操作,可以执行操作
            clearTimeout(timer)
            timer = null
            handle.apply(self,args)
            previous = new Date()
        }else if(!timer){
            //当我们发现系统中有一个定时器了，就意味着我们不需要再开定时器
            //此刻就说明这次的操作发生了在我们定义的频次时间范围内，那就不应该执行handle
            // 这个时候我们就可以自定义一个定时器，让handle在interval之后去执行
            timer = setTimeout(()=>{
                clearTimeout(timer) //清除定时器
                timer = null
                handle.apply(self,args)
                previous = new Date()
            },interval)
        }
    }
}


// 节流函数
//通过定时器实现(简洁版)
function throttle2(fn, wait = 1000, immediate = false) {
  let flag = true
  let timer = null
  return function(...args) {
    if (flag) {
      //是否立即执行
      immediate && fn.apply(this, args)
      //关闭通道，等待定时器执行完后再开启
      flag = false
      timer = setTimeout(() => {
        !isImmediate && fn.apply(this, args)
        flag = true
      }, wait)
    }
  }
}

</script>
</html>